package com.example.im.db

import android.content.Context
import android.text.TextUtils
import androidx.room.Room
import com.example.im.app.ImApplication
import com.example.im.bean.*
import com.example.im.common.Constants
import com.example.im.utils.JsonUtils
import com.example.im.utils.LogUtils
import com.example.im.utils.MD5Utils
import org.jivesoftware.smack.packet.Message
import org.jivesoftware.smack.roster.RosterEntry
import org.jivesoftware.smackx.muc.RoomInfo
import java.text.SimpleDateFormat
import java.util.*

object DatabaseStorage {

    fun initDatabaseCreate(dbName: String) {
        ImApplication.appDatabase = Room.databaseBuilder(
            ImApplication.context(), AppDatabase::class.java, dbName
        )
            .allowMainThreadQueries().build()
    }

    /**
     * 保存信息
     *
     * @param userRoom （花名册/聊天室）信息
     * @return FriendOrRoom实体
     * */
    @Synchronized
    fun setUserRoomStorage(userRoom: UserRoom): UserRoom? {

        val appDatabase = ImApplication.appDatabase
            ?: return null

        val userRoomDB = getUserRoomStorageByAccount(userRoom.account ?: return null)
        if (userRoomDB != null) {
            //更新数据库
            val friendOrRoomNew = with(userRoom) {
                this.id = userRoomDB.id
                this.getUserRoom()
            }
            appDatabase.userRoomDao()
                .update(friendOrRoomNew)
            return friendOrRoomNew
        }
        //写入数据库
        val id = appDatabase.userRoomDao().insert(userRoom)
        //获取最新数据
        return appDatabase.userRoomDao()
            .selectUserRoomByID(id.toInt())
    }

    /**
     * 保存花名册信息
     *
     * @param roster 花名册录入
     * @return FriendOrRoom实体
     * */
    fun setUserRoomStorage(roster: RosterEntry): UserRoom? {
        val friendOrRoom = with(UserRoom(), {
            this.jid = roster.jid.intern()
            this.account = roster.jid.localpartOrNull.intern()
            this.nickname = roster.name
            this.type = Message.Type.chat.ordinal
            this.sub = roster.type.ordinal
            this.getUserRoom()
        })
        return setUserRoomStorage(friendOrRoom)
    }

    /**
     * 保存聊天室信息
     *
     * @param room 聊天室信息
     * @return FriendOrRoom实体
     * */
    fun setUserRoomStorage(room: RoomInfo, sub: Int): UserRoom? {
        val friendOrRoom = with(UserRoom(), {
            this.jid = room.room.intern()
            this.account = room.room.localpart.intern()
            this.nickname = room.name
            this.type = Message.Type.groupchat.ordinal
            this.sub = sub
            this.getUserRoom()
        })
        return setUserRoomStorage(friendOrRoom)
    }

    fun upUserRoomSub(sub: Int, uid: Int) {
        val appDatabase = ImApplication.appDatabase
            ?: return
        appDatabase.userRoomDao().upDateUserRoomSub(sub, uid)
    }


    /**
     * 根据用户类型获取好友/聊天室
     *
     * @param type 用户类型
     * */
    fun getUserRoomStorageByType(type: Int): MutableList<UserRoom>? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.userRoomDao()
            .selectUserRoomByType(type) ?: null
    }

    /**
     * 获取本地好友列表
     * */
    fun getUserRoomToUser(): List<UserRoom>? = getUserRoomStorageByType(Constants.CHAT_KIND_1)

    fun getUserRoomToUserAll():List<UserRoom>?{
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.userRoomDao()
            .selectUserRoomByTypeAll(Constants.CHAT_KIND_1) ?: null
    }

    /**
     * 获取本地群聊列表
     * */
    fun getUserRoomToRoom(): List<UserRoom>? = getUserRoomStorageByType(Constants.CHAT_KIND_2)

    /**
     * 获取本地好友请求列表
     * */
    fun getUserRoomToRequest(): List<UserRoom>? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.userRoomDao()
            .selectUserRoomByTypeAndSub(Constants.CHAT_KIND_1, Constants.USER_ROOM_SUB_2)
    }


    /**
     * 搜索好友
     * */
    fun setUserRoomSearch(search: String): List<UserRoom> {
        val appDatabase = ImApplication.appDatabase
            ?: return mutableListOf()
        return appDatabase.userRoomDao().selectUserRoomBySearch(search)
    }

    /**
     * 根据账户名获取信息
     * @param account 账户名
     * */
    fun getUserRoomStorageByAccount(account: String): UserRoom? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.userRoomDao()
            .selectUserRoomByAccount(account) ?: null
    }

    /**
     * 根据用户类型获取好友/聊天室
     *
     * @param type 用户类型
     * */
    fun getUserRoomStorageById(id: Int): UserRoom? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.userRoomDao()
            .selectUserRoomByID(id) ?: null
    }

    /**
     * 删除用户相关数据，包含聊天记录
     * */
    fun deleteUserRoomStorage(userRoom: UserRoom) {
        val appDatabase = ImApplication.appDatabase
            ?: return
        appDatabase.userRoomDao().delete(userRoom)
    }

    /**
     * 保存聊天消息
     *
     * @param account 用户信息
     * @param msg 消息内容
     * @param status 发送状态
     * @param or 发送1，接收2
     * */
    fun setChatRecordStorage(
        userRoom: UserRoom,
        chatBody: ChatBody,
        from: String?,
        to: String?,
        kind: Int,
        action: Int,
        status: Int
    ): ChatLast? {

        val encrypt = MD5Utils.parseStrToMd5U16(chatBody.time.toString())

        val appDatabase = ImApplication.appDatabase
            ?: return null

        val chatRecord = appDatabase.chatRecordDao()
            .selectChatRecordByEncrypt(encrypt)

        val chatRecordNew = with(chatRecord ?: ChatRecord(), {
            this.uid = userRoom.id
            this.from = from
            this.to = to
            this.kind = kind
            this.or = action
            this.status = status
            this.body = chatBody.body
            this.aits = chatBody.aits
            this.time = chatBody.time
            this.type = chatBody.type
            this.file = chatBody.file
            this.encrypt = encrypt
            this.json = chatBody.toString()
            this.getChatRecord()
        })

        val chatTotalId = if (chatRecord != null) {
            appDatabase.chatRecordDao().update(chatRecordNew)
            chatRecordNew.id
        } else {
            appDatabase.chatRecordDao().insert(chatRecordNew).toInt()
        }

        LogUtils.e(
            JsonUtils.objectToString(
                appDatabase.chatRecordDao().selectChatRecordByID(chatTotalId)
            )
        )

        val chatLast = appDatabase.chatLastDao()
            .selectChatLastsByUid(userRoom.id)
        val chatLastsNew = with(chatLast ?: ChatLast(), {
            this.uid = userRoom.id
            this.tid = chatTotalId
            if (!this.isAit) chatRecordNew.aits?.forEach {
                val userJid = getAccountInfoStorage().username
                    ?: return@forEach
                if (it.contains(userJid))
                    this.isAit = true
            }
            this.getChatLast()
        })
        if (chatLast == null) {
            val id = appDatabase.chatLastDao().insert(chatLastsNew)
            chatLastsNew.id = id.toInt()
        } else {
            appDatabase.chatLastDao().update(chatLastsNew)
        }
        LogUtils.e(JsonUtils.objectToString(chatLastsNew))
        return chatLastsNew
    }


    fun setChatRecordTime(uid: Int, nextTime: Long): ChatRecord? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        val backTime = appDatabase.chatRecordDao()
            .selectChatRecordByUidToLimitTime(uid)

        if ((nextTime - backTime) < (60 * 1000 * 5)) {
            return null
        }
        val chatRecord = with(ChatRecord(), {
            this.uid = uid
            this.body = SimpleDateFormat("MM-dd HH:mm", Locale.getDefault())
                .format(Date(nextTime))
            this.time = nextTime
            this.or = Constants.CHAT_ACTION_3
            this.type = Constants.CHAT_TYPE_TIME
            this.encrypt = MD5Utils.parseStrToMd5U16(body)
            this.getChatRecord()
        })

        val chatRecordId = appDatabase.chatRecordDao()
            .insert(chatRecord)

        return appDatabase.chatRecordDao()
            .selectChatRecordByID(chatRecordId.toInt())
    }

    /**
     * 根据uid获取聊天记录
     * */
    fun getChatRecordStorage(uid: Int): List<ChatRecord> {
        val appDatabase = ImApplication.appDatabase
            ?: return mutableListOf()
        return appDatabase.chatRecordDao().selectChatRecordByUid(uid)
    }


    /**
     * 根据uid获取聊天记录
     * */
    fun getChatRecordToId(id: Int): ChatRecord? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        return appDatabase.chatRecordDao().selectChatRecordByID(id)
    }


    /**
     * 更新聊天记录状态
     * */
    fun upChatRecordStatus(newStatus: Int, oldStatus: Int, uid: Int) {
        val appDatabase = ImApplication.appDatabase
            ?: return
        appDatabase.chatRecordDao().upDateChatRecordStatus(newStatus, oldStatus, uid)
    }

    /**
     * 更新最后记录状态
     * */
    fun upChatLastIsAit(isAit: Boolean, uid: Int) {
        val appDatabase = ImApplication.appDatabase
            ?: return
        appDatabase.chatLastDao().upDateChatLastsByAit(isAit, uid)
    }

    /**
     *
     * */

    /**
     * 根据UID获取最后一条记录
     * */
    fun getChatLastId(uid: Int): ChatEntry? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        val chatLast = appDatabase.chatLastDao().selectChatLastsByUid(uid)
            ?: return null
        return getChatEntryStorage(chatLast)
    }

    /**
     * 获取聊天列表信息
     *
     * @param last
     * */
    fun getChatEntryStorage(last: ChatLast): ChatEntry? {
        val appDatabase = ImApplication.appDatabase
            ?: return null
        val userRoom = appDatabase.userRoomDao().selectUserRoomByID(last.uid)
            ?: return null
        val chatRecord = appDatabase.chatRecordDao().selectChatRecordByID(last.tid)
            ?: return null
        val unread = appDatabase.chatRecordDao().countUnread(last.uid)
        return with(ChatEntry(), {
            this.userRoom = userRoom
            this.chatLast = last
            this.chatRecord = chatRecord
            this.unread = unread
            this.getChatEntry()
        })
    }

    /**
     * 获取聊天列表信息
     * */
    fun getChatEntryStorage(): List<ChatEntry> {
        val chatEntrys = mutableListOf<ChatEntry>()
        val appDatabase = ImApplication.appDatabase
            ?: return chatEntrys
        val chatLasts = appDatabase.chatLastDao().loadAll()
        chatLasts.forEach {
            val last = getChatEntryStorage(it)
            if (last != null) chatEntrys.add(last)
        }
        return chatEntrys
    }

    /**
     * 获取聊天记录全部未读信息数量
     * */
    fun getChatRecordUnread(): Int {
        val appDatabase = ImApplication.appDatabase
            ?: return 0
        return appDatabase.chatRecordDao().countUnread()
    }

    /**
     * 获取好友请求全部未读信息数量
     * */
    fun getUserRoomUnread(): Int {
        val appDatabase = ImApplication.appDatabase
            ?: return 0
        return appDatabase.userRoomDao().countUnread()
    }


    /**
     * 删除用户的聊天记录
     * */
    fun deleteChatRecordStorage(userRoom: UserRoom) {
        val appDatabase = ImApplication.appDatabase
            ?: return
        appDatabase.chatLastDao().delete(userRoom.id)
        appDatabase.chatRecordDao().delete(userRoom.id)
    }

    /**
     * 保存账户信息
     * */
    fun setAccountInfoStorage(jid: String, name: String, username: String, email: String) {
        val account = with(Accounts(), {
            this.jid = jid
            this.name = name
            this.username = username
            this.email = email
            this.getAccount()
        })
        ImApplication.appDatabase().accountDao().insert(account)
    }

    /**
     * 获取账户信息
     * */
    fun getAccountInfoStorage(): Accounts =
        ImApplication.appDatabase().accountDao().account()

    /**
     * 获取登录账号密码
     * */
    fun getAccountAndPassword(): MutableMap.MutableEntry<String, String>? {
        val preferences = ImApplication.context()
            .getSharedPreferences(Constants.ACCOUNT_ATTRIBUTES, Context.MODE_PRIVATE)
        val userName = preferences.getString(Constants.ACCOUNT_USER_NAME, null)
        val password = preferences.getString(Constants.ACCOUNT_PASSWORDS, null)
        if (userName.isNullOrEmpty() && password.isNullOrEmpty())
            return null
        return AbstractMap.SimpleEntry<String, String>(userName, password)
    }

    /**
     * 保存登录账号密码
     * */
    fun setAccountAndPassword(userName: String, password: String) {
        val preferences = ImApplication.context()
            .getSharedPreferences(Constants.ACCOUNT_ATTRIBUTES, Context.MODE_PRIVATE)
        val editor = preferences.edit()
        editor.putString(Constants.ACCOUNT_USER_NAME, userName)
        editor.putString(Constants.ACCOUNT_PASSWORDS, password)
        editor.apply()
    }

    /**
     * 判断是否登录过
     * */
    fun isAccountAndPassword(): Boolean {
        val account = getAccountAndPassword()
            ?: return false
        return !(TextUtils.isEmpty(account.key) || TextUtils.isEmpty(account.value))
    }


}
